#include "vertex_buffer_opengl.h"

using namespace krryn::system_imp;

vertex_buffer_opengl::vertex_buffer_opengl(size_t a_VertexSizeInBytes, size_t a_NumberOfVertices) 
	: vertex_buffer(a_VertexSizeInBytes, a_NumberOfVertices)
{
	glGenBuffersARB(1, &m_BufferId);
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_BufferId);
	glBufferDataARB(GL_ARRAY_BUFFER_ARB, get_size_in_bytes(), 0, GL_STATIC_DRAW_ARB);
}

vertex_buffer_opengl::~vertex_buffer_opengl(){
	glDeleteBuffersARB(1, &m_BufferId);
}

void vertex_buffer_opengl::write_data(size_t a_OffsetInBytes, size_t a_SizeInBytes, const void *a_Source){
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_BufferId);
	glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, a_OffsetInBytes, a_SizeInBytes, a_Source);
}

void vertex_buffer_opengl::read_data(size_t a_OffsetInBytes, size_t a_SizeInBytes, void *a_Destination){
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_BufferId);
	glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, a_OffsetInBytes, a_SizeInBytes, a_Destination);
}

GLuint vertex_buffer_opengl::get_buffer_id() const { return m_BufferId; }

void* vertex_buffer_opengl::lock_impl(){
	GLenum l_Mode = -1;

	if(locked() == read)			l_Mode = GL_READ_ONLY_ARB;
	else if(locked() == write)		l_Mode = GL_WRITE_ONLY_ARB;
	else if(locked() == read_write)	l_Mode = GL_READ_WRITE_ARB;

	glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_BufferId);
	return glMapBufferARB(GL_ARRAY_BUFFER_ARB, l_Mode);
}

void vertex_buffer_opengl::unlock_impl(){
	glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_BufferId);
	glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
}